package com.wenjoying.common.utils;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author wenjoying@126.com
 * @date 2019-11-27 10:28
 */
@Component
public class FunctionUtil {
    /** 空字符串 */
    private static final String EMPTY_STR = "";

    public static String getHostDomain(HttpServletRequest request) {
        return request.getScheme() + "://" +request.getServerName();
    }

    /**
     * 获取客户端IP
     * @param request
     * @return
     */
    public static String getIpAddress(HttpServletRequest request) {
        if (request == null) {
            return "";
        }

        String ip = request.getHeader("X-Requested-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Forwarded-For");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        if("0:0:0:0:0:0:0:1".equals(ip)){
            return "127.0.0.1";
        }
        return ip;
    }

    /**
     * 获取本机IP
     * @return
     */
    public static String getLocalIp() {
        try {
            InetAddress ip4 = Inet4Address.getLocalHost();
            return ip4.getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * @param phone 字符串类型的手机号
     * 传入手机号,判断后返回
     * true为手机号,false相反
     * */
    public static boolean isPhone(String phone) {
//        String regex = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[0-9]))\\d{8}$";
        String regex = "^1\\d{10}$";
        if (phone.length() != 11) {
            return false;
        } else {
            Pattern p = Pattern.compile(regex);
            Matcher m = p.matcher(phone);
            return m.matches();
        }
    }

    /**
     * @param phone 字符串类型的手机号
     * 传入固话,判断后返回
     * true为固话,false相反
     * */
    public static boolean isFixPhone(String phone) {
        String regex1 = "^(0[0-9]{2,3}\\-)([0-9]{5,10})$";
        String regex2 = "^[1-9]{1}[0-9]{5,8}$";
        Pattern p = null;
        if (phone.length() > 9) {
            // 验证带区号的
            p = Pattern.compile(regex1);
        } else {
            // 验证没有区号的
            p = Pattern.compile(regex2);
        }
        Matcher m = p.matcher(phone);
        return m.matches();
    }

    /**
     * @param str 全是数字
     * 传入固话,判断后返回
     * true为数字,false相反
     * */
    public static boolean isNum(String str) {
        String regex = "[0-9]+";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(str);
        return m.matches();
    }

    /**
     * @param str 全是字母
     * 传入固话,判断后返回
     * true为字母,false相反
     * */
    public static boolean isChar(String str) {
        String regex = "[a-z]+";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(str.toLowerCase());
        return m.matches();
    }

    /**
     * @param str 全是中文
     * 传入固话,判断后返回
     * true为汉字,false相反
     * */
    public static boolean isChinese(String str) {
        String regex = "[\u4e00-\u9fa5]+";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(str.toLowerCase());
        return m.matches();
    }

    /**
     * 随机字符串
     * @param length
     * @param type
     * @return
     */
    public static String getRandomString(int length, int type){
        String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        String num = "0123456789";
        String rand = type==1?str:(type==2?num:(str+num));
        Random random=new Random();
        StringBuffer sb=new StringBuffer();
        for(int i=0;i<length;i++){
            int number=random.nextInt(rand.length());
            sb.append(rand.charAt(number));
        }
        return sb.toString();
    }

    /**
     * 判断一个对象是否为空
     * @param object Object
     * @return true：为空 false：非空
     */
    public static boolean isNull(Object object)
    {
        return object == null;
    }

    /**
     * 判断一个字符串是否为空串
     * @param str String
     * @return true：为空 false：非空
     */
    public static boolean isEmpty(String str)
    {
        return isNull(str) || EMPTY_STR.equals(str.trim());
    }

    /**
     * List
     * @param arr List
     * @return true：为空 false：非空
     */
    public static boolean isEmpty(List arr)
    {
        return isNull(arr) || arr.isEmpty();
    }

    /**
     * 判断一个jsonarrar是否为空
     * @param arr JSONArray
     * @return true：为空 false：非空
     */
    public static boolean isEmpty(JSONArray arr)
    {
        return isNull(arr) || arr.isEmpty();
    }

    /**
     * 判断一个jsonarrar是否为空
     * @param json JSONArray
     * @return true：为空 false：非空
     */
    public static boolean isEmpty(JSONObject json) { return isNull(json) || json.isEmpty(); }

    /**
     * 判断一个字符串是否为空串
     * @param object 对象
     * @return true：为空 false：非空
     */
    public static boolean isEmpty(Object object)
    {
        return isNull(object) || isEmpty(object.toString());
    }

    /**
     * 计算并获取CheckSum
     * @param nonce 随机数
     * @param curTime 时间戳
     * @return
     */
    public static String getCheckSum(String edcSecret, String nonce, long curTime) {
        try {
            //记住：1要反转私钥字符串，2. 是私钥，不是传递在httpheader中的公钥
            String secret = new StringBuffer(edcSecret).reverse().toString();
            String message = new StringBuffer(nonce).append(curTime).toString();

            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
            sha256_HMAC.init(secret_key);

            String hash = Base64.getEncoder().encodeToString(sha256_HMAC.doFinal(message.getBytes()));
            return hash;
        } catch (Exception e){
            System.out.println("Error");
            return null;
        }
    }

    /**
     * 获取list
     * @param arr
     * @param index指定index的值
     * @return
     */
    public static String getValueByIndex(List<String> arr, Integer index) {
        try {
            return arr.get( index );
        } catch ( Exception e ) {
            return "";
        }
    }

    /**
     * 默认为空
     * @param str
     * @return
     */
    public static String getDefultBlank(String str) {
        try {
            if (isEmpty(str)) {
                return "";
            }
            return str;
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 取差集
     * @param list1
     * @param list2
     * @return
     */
    public static List diffSet(List list1, List list2) {
        List l1 = new ArrayList();
        l1.addAll(list1);

        List l2 = new ArrayList();
        l2.addAll(list2);

        l1.removeAll(l2);
        return l1;
    }

    /**
     * 取交集
     * @param list1
     * @param list2
     * @return
     */
    public static List bothSet(List list1, List list2) {
        List l1 = new ArrayList();
        l1.addAll(list1);

        List l2 = new ArrayList();
        l2.addAll(list2);

        l1.retainAll(l2);
        return l1;
    }

    /**
     * 验证邮箱格式
     * @param email
     * @return
     */
    public static boolean isEmail(String email){
        String regex = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(email);
        return m.matches();
    }

    /**
     * 获取随机数
     * @param a
     * @param b
     * @return
     */
    public static int random(int a,int b) {
        int temp = 0;
        try{
            if(a>b){
                temp = new Random().nextInt(a-b);
                return temp+b;
            }else{
                temp = new Random().nextInt(b-a);
                return temp+a;
            }
        }catch(Exception e){
            e.printStackTrace();
        }

        return temp+a;
    }

    /**
     * 读取文件
     * @param filename
     * @return
     */
    public static String readPem(String filename) {
        List<String> list = new ArrayList<>();
        try {
            //resources下文件只能读取流
            InputStream file = new ClassPathResource(filename).getInputStream();
            list = IoUtil.readLines(file, "UTF-8", list);
            if (list.size()>1) {
                list.remove(list.size()-1);
                list.remove(0);
            }
        } catch (Exception e) {
e.printStackTrace();
        }

        return list.toString();
    }

    /**
     * openssl签名
     * @param data
     * @return
     */
    public static String opensslSign(String data, String privateKeyStr, String publicKeyStr) {
        if (isEmpty(privateKeyStr) || isEmpty(publicKeyStr)) {
            privateKeyStr = readPem("storage/janssen/rsa_private_key.pem");
            publicKeyStr = readPem("storage/janssen/rsa_public_key.pem");
        }

        RSA rsa = new RSA(privateKeyStr, publicKeyStr);
        byte[] encrypt = rsa.encrypt(StrUtil.bytes(data, CharsetUtil.CHARSET_UTF_8), KeyType.PrivateKey);

        return Base64.getEncoder().encodeToString(encrypt);
    }

    /**
     * openssl验签
     * @param data
     * @param encrypt
     * @return
     */
    public static Boolean verifySign(String data, String encrypt, String privateKeyStr, String publicKeyStr) {
        if (isEmpty(privateKeyStr) || isEmpty(publicKeyStr)) {
            privateKeyStr = readPem("storage/janssen/rsa_private_key.pem");
            publicKeyStr = readPem("storage/janssen/rsa_public_key.pem");
        }

        RSA rsa = new RSA(privateKeyStr, publicKeyStr);
        byte[] decrypt = rsa.decrypt(Base64.getDecoder().decode(encrypt), KeyType.PublicKey);

        return data.equals(StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8));
    }

    /**
     * 转化为erp的参数
     * @return
     */
    public static JSONObject toErpParam(JSONObject jsonObject, JSONObject keyOprate) {
        JSONObject param = new JSONObject();
        keyOprate.forEach((key, operation)->{
            if (!isEmpty(jsonObject.getString(key))) {
                Map map1 = new HashMap();
                if ("between".equals(operation)) {
                    String[] timeArr = jsonObject.getString("plan_contact_time").split("\\|");
                    JSONArray arr = new JSONArray();
                    arr.add(timeArr[0]+" 00:00:00");
                    arr.add(timeArr[1]+" 23:59:59");
                    map1.put("value", arr);
                } else {
                    map1.put("value", jsonObject.getString(key));
                }

                map1.put("operation", operation);
                param.put(key, map1);

            }
        });
        System.err.println(param);
        return param;
    }

}
